package com.taotao.delayjob.example.conf;

import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateDeserializer;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalTimeDeserializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateSerializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalTimeSerializer;
import com.taotao.delayjob.example.conf.mvc.StringTrimConverter;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.web.servlet.MultipartConfigFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.format.FormatterRegistry;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.StringHttpMessageConverter;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.servlet.DispatcherServlet;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.PathMatchConfigurer;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

import javax.servlet.MultipartConfigElement;
import java.io.File;
import java.nio.charset.Charset;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.util.List;
import java.util.Objects;

/**
 * spring mvc 的配置
 */
@Configuration
public class WebConfiguration implements WebMvcConfigurer {
    @Value("${virtual.data.prefix:/data}")
    private String dataUrlPrefix;

    @Value("${virtual.data.path:/opt/data/web}")
    private String dataPath;

    @Value("${spring.profiles.active}")
    private String env;

    @Override
    public void addArgumentResolvers(List<HandlerMethodArgumentResolver> argumentResolvers) {
//        argumentResolvers.add(new TrimParamArgumentResolver());
//        argumentResolvers.add(new UserInfoArgumentResolver());
    }





    @Override
    public void addFormatters(FormatterRegistry registry) {
        registry.addConverter(new StringTrimConverter());
    }



    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {

        //排除静态文件

        // swagger
        if(!Objects.equals("prd",env)){
            // 线上环境不暴露swagger
            registry.addResourceHandler("doc.html")
                    .addResourceLocations("classpath:/META-INF/resources/");

            registry.addResourceHandler("/swagger-resources/**")
                    .addResourceLocations("classpath:/META-INF/resources/webjars/");

            registry.addResourceHandler("/webjars/**")
                    .addResourceLocations("classpath:/META-INF/resources/webjars/");
        }


        registry.addResourceHandler("/index.html").addResourceLocations(
                "classpath:META-INF/delayjob/index.html");
        // delay-job-lite 管理页面
        registry.addResourceHandler("/**")
                .addResourceLocations("classpath:META-INF/delayjob/");


//        registry.addResourceHandler("/**").addResourceLocations(
//                "classpath:/static/");



        // 文件磁盘图片url 映射 配置server虚拟路径，handler为前台访问的目录，locations为files相对应的本地路径
//        registry.addResourceHandler(dataUrlPrefix).addResourceLocations(dataPath);
    }
    @Override
    public void addViewControllers(ViewControllerRegistry registry) {
        //第一个路径为类似于Controller中的接口的路径 第二个view为要访问的页面
        //实现不需要进行数据渲染的页面的路径映射 当然这些页面没有在默认的五个静态页面访问路径下
        registry.addRedirectViewController("/", "/doc.html");

//        registry.addViewController("/hopec").setViewName("hello");
    }


    @Bean
    public HttpMessageConverter<String> responseBodyConverter() {
        StringHttpMessageConverter converter = new StringHttpMessageConverter(Charset.forName("UTF-8"));
        return converter;
    }

    @Bean
    public MultipartConfigElement multipartConfigElement() {
        MultipartConfigFactory factory = new MultipartConfigFactory();
        String path = System.getProperty("user.home") + File.separator + ".tmp" + File.separator + "clearing" + System.currentTimeMillis();
        File file = new File(path);
        if (!file.exists()) {
            file.mkdirs();
        }

        factory.setLocation(path);
        return factory.createMultipartConfig();
    }


    @Override
    public void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
        converters.add(responseBodyConverter());
    }

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
//        registry.addInterceptor(new InnerApiHandlerInterceptor());
    }

    @Override
    public void configurePathMatch(PathMatchConfigurer configurer) {
        // setUseSuffixPatternMatch 后缀模式匹配
        configurer.setUseSuffixPatternMatch(false);
        // setUseTrailingSlashMatch 自动后缀路径模式匹配
        configurer.setUseTrailingSlashMatch(true);
    }

    @Bean
    public DispatcherServlet dispatcherServlet() {
        DispatcherServlet dispatcherServlet = new DispatcherServlet();
        dispatcherServlet.setThrowExceptionIfNoHandlerFound(true);
        return dispatcherServlet;
    }

    @Override
    public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {

        /**
         * 交换MappingJackson2HttpMessageConverter与第一位元素
         * 让返回值类型为String的接口能正常返回包装结果
         *
         */
        for (int i = 0; i < converters.size(); i++) {
            if (converters.get(i) instanceof MappingJackson2HttpMessageConverter) {
                MappingJackson2HttpMessageConverter mappingJackson2HttpMessageConverter = (MappingJackson2HttpMessageConverter) converters.get(i);
                converters.set(i, converters.get(0));
                converters.set(0, mappingJackson2HttpMessageConverter);
                break;
            }
        }


        for (HttpMessageConverter converter : converters) {
            if (converter instanceof MappingJackson2HttpMessageConverter) {
                ObjectMapper objectMapper = ((MappingJackson2HttpMessageConverter) converter).getObjectMapper();
                // 忽略空字段
                objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
                // 忽略没有的字段
                objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
                JavaTimeModule javaTimeModule = new JavaTimeModule();

                // 设定LocalDateTime的默认格式
                javaTimeModule.addSerializer(LocalDateTime.class, new LocalDateTimeSerializer(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
                javaTimeModule.addSerializer(LocalDate.class, new LocalDateSerializer(DateTimeFormatter.ofPattern("yyyy-MM-dd")));
                javaTimeModule.addSerializer(LocalTime.class, new LocalTimeSerializer(DateTimeFormatter.ofPattern("HH:mm:ss")));

                javaTimeModule.addDeserializer(LocalDateTime.class, new LocalDateTimeDeserializer(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
                javaTimeModule.addDeserializer(LocalDate.class, new LocalDateDeserializer(DateTimeFormatter.ofPattern("yyyy-MM-dd")));
                javaTimeModule.addDeserializer(LocalTime.class, new LocalTimeDeserializer(DateTimeFormatter.ofPattern("HH:mm:ss")));

                objectMapper.registerModule(javaTimeModule);

            }
        }
    }

}